package spring.framework.beans.factory.support;

import spring.framework.beans.BeansException;
import spring.framework.beans.factory.BeanFactory;
import spring.framework.beans.factory.config.BeanDefinition;

/**
 * @author pengzh
 * @class AbstractBeanFactory
 * @since 2021-09-23
 * 抽象工厂 模板模式
 */
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {


    @Override
    public Object getBean(String beanName) throws BeansException {
        return doGetBean(beanName, Object.class, null);
    }

    @Override
    public Object getBean(String beanName, Object... args) throws BeansException {
        return doGetBean(beanName, Object.class, args);
    }

    @Override
    public <T> T getBean(String beanName, Class<T> classType) throws BeansException {
        return doGetBean(beanName, null);
    }

    @Override
    public  <T> T getBean(String beanName, Class<T> classType, Object... args) throws BeansException {
        return doGetBean(beanName, classType, args);
    }

    protected <T> T doGetBean(String beanName, Class<T> classType, Object... args) throws BeansException {
        Object bean = getSingleton(beanName);
        if (null != bean) {
            return (T) bean;
        }
        BeanDefinition beanDefinition = getBeanDefinition(beanName);
        return (T) createBean(beanName, beanDefinition, args);
    }

    protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;


    protected abstract Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException;

}
